1 00:00:00,540 --> 00:00:01,290 Welcome. 2 00:00:01,290 --> 00:00:06,450 In this lecture we're going to look at a concept in object oriented programming called encapsulation. 3 00:00:06,720 --> 00:00:12,330 Encapsulation is the idea that we should encapsulate functions and methods together into a single unit, 4 00:00:12,330 --> 00:00:14,310 which we've been doing with our classes. 5 00:00:14,310 --> 00:00:18,420 But we should also limit access to the data when needed. 6 00:00:18,420 --> 00:00:23,640 So if there's any properties in an object we create, we want to limit access to that data. 7 00:00:23,640 --> 00:00:27,180 And we may also want to limit changes to that data as well. 8 00:00:27,210 --> 00:00:32,340 In our previous lectures, you may have seen how we've used the underscore underscore index meta method 9 00:00:32,340 --> 00:00:36,570 directly within the class itself, and use the class as the meta table. 10 00:00:36,600 --> 00:00:41,910 However, the problem with doing this means that we can create new objects by calling the new function 11 00:00:41,910 --> 00:00:45,480 from that object itself, which sometimes we don't want to do. 12 00:00:45,510 --> 00:00:48,930 So as an example, if I had a human class. 13 00:00:49,770 --> 00:00:54,000 And I set the underscore underscore index meta method to itself. 14 00:00:54,120 --> 00:00:57,390 And then I had a constructor for this class. 15 00:00:59,260 --> 00:01:00,850 And we'll just return a new table. 16 00:01:00,850 --> 00:01:01,570 Whatever. 17 00:01:02,140 --> 00:01:08,140 Or actually, we return a new table with a meta table attached to it, which is the human class. 18 00:01:08,650 --> 00:01:10,750 If we were to create a new human. 19 00:01:12,790 --> 00:01:13,540 From this point. 20 00:01:13,540 --> 00:01:17,920 This new human also has the constructor inside of it, which we don't want to happen. 21 00:01:17,920 --> 00:01:23,230 We only want to be able to access the constructor from the main class or the table itself. 22 00:01:23,230 --> 00:01:25,180 So how can we avoid doing this? 23 00:01:26,690 --> 00:01:33,080 Well, what we could do is we could create a second table and I'm going to call it human meta table. 24 00:01:33,080 --> 00:01:38,570 And the purpose of this table is to act as our meta table for creating new human objects, and as well 25 00:01:38,570 --> 00:01:42,110 to store all of the functions that the human class is going to use. 26 00:01:42,110 --> 00:01:46,820 The only purpose of this table is going to hold our constructor, and that's it. 27 00:01:46,820 --> 00:01:49,100 We're not going to put any other implementation in here. 28 00:01:49,100 --> 00:01:51,170 It's just going to hold our constructor. 29 00:01:51,770 --> 00:01:56,750 So that means when we create a new human object we can set it to the human meta table. 30 00:01:57,680 --> 00:02:00,800 And we'll make sure to get rid of this. 31 00:02:00,800 --> 00:02:07,490 And instead set the underscore underscore index meta method inside of the human meta table to itself. 32 00:02:08,070 --> 00:02:13,290 Now, if we were to pass a name to create for this new human, we could do that just right here. 33 00:02:13,290 --> 00:02:15,810 I'll create a table called self. 34 00:02:16,470 --> 00:02:18,780 And actually we'll just copy this here and put it there. 35 00:02:20,660 --> 00:02:26,540 And then inside of this human meta table, I can also define, um, what properties a human table should 36 00:02:26,540 --> 00:02:26,960 have. 37 00:02:26,960 --> 00:02:28,430 So like the name. 38 00:02:30,420 --> 00:02:31,740 We'll leave it blank for now. 39 00:02:31,740 --> 00:02:37,320 And the from here we can set the name equal to the name passed to the function and then return self. 40 00:02:38,270 --> 00:02:39,710 Now by doing it this way. 41 00:02:39,710 --> 00:02:41,570 If I were to create a new human. 42 00:02:44,330 --> 00:02:47,150 Human dot new and pass a name like Bob. 43 00:02:48,170 --> 00:02:52,100 I'm no longer able to access the dot new function. 44 00:02:52,250 --> 00:02:54,650 I can only do it from the human class. 45 00:02:54,650 --> 00:02:58,010 No longer am I able to do it from the object itself, which is good. 46 00:02:58,010 --> 00:02:59,450 We fixed that problem. 47 00:02:59,450 --> 00:03:05,060 However, let's say another problem is that I don't want people adding new properties into this table. 48 00:03:05,060 --> 00:03:06,410 I don't want that to happen. 49 00:03:06,710 --> 00:03:09,830 Perhaps I only want it to have a name and nothing else. 50 00:03:09,830 --> 00:03:13,580 But in its current state, I can add whatever properties I want into this table. 51 00:03:13,580 --> 00:03:14,960 I can add age. 52 00:03:14,960 --> 00:03:20,120 I can add, you know, any, um, any key value pairs into this table. 53 00:03:20,120 --> 00:03:21,710 How could I avoid doing that? 54 00:03:21,710 --> 00:03:28,460 Well, inside of the human meta table, I could set a new meta method called new index, which gets 55 00:03:28,460 --> 00:03:32,030 fired when we try to create a new index in a table. 56 00:03:32,150 --> 00:03:35,150 And what we could do is set it to equal to a function. 57 00:03:35,450 --> 00:03:42,110 And what we'll do is we'll just raise an error and say something like unable to add new index to this 58 00:03:42,110 --> 00:03:42,920 object. 59 00:03:43,520 --> 00:03:49,400 And that means if I try to add a new property like age to my human, it should error. 60 00:03:50,810 --> 00:03:51,770 And there we go. 61 00:03:51,800 --> 00:03:54,260 Unable to add new index to this object. 62 00:03:54,320 --> 00:04:01,130 So just like that, we've disabled the ability for us to create new, um, new indexes within our human 63 00:04:01,160 --> 00:04:01,970 object. 64 00:04:02,770 --> 00:04:08,500 Now, let's also say I want to prevent us from being able to change the name directly from the table 65 00:04:08,500 --> 00:04:12,880 itself, because in its current state, I can rename this to whatever I want. 66 00:04:12,880 --> 00:04:16,090 But sometimes that kind of functionality isn't desired. 67 00:04:16,090 --> 00:04:17,890 So how can we avoid this? 68 00:04:18,340 --> 00:04:24,430 Well, another way we could do it is that we could create a table, and I'm going to call it private 69 00:04:24,430 --> 00:04:25,330 data. 70 00:04:25,990 --> 00:04:32,830 And instead of setting the name directly within the object itself, what I could do is I could create 71 00:04:32,830 --> 00:04:33,670 a new table in here. 72 00:04:33,670 --> 00:04:34,900 I'll call it private. 73 00:04:35,800 --> 00:04:40,240 And I'll set the name for our human inside of this table instead. 74 00:04:41,350 --> 00:04:42,880 And then from that point. 75 00:04:44,120 --> 00:04:48,080 I could create a new key value pair within the private data table. 76 00:04:48,260 --> 00:04:49,520 Private data. 77 00:04:49,760 --> 00:04:54,590 The key for this private data table is going to be the object itself. 78 00:04:54,830 --> 00:05:00,710 And then I'm going to set it equal to this private table right here. 79 00:05:01,010 --> 00:05:08,180 So that means if I ever wanted to access the name of my human, I would have to have access to this 80 00:05:08,180 --> 00:05:13,310 private data table, which can only be accessed if you have the object itself. 81 00:05:13,310 --> 00:05:21,260 So that means I'm no longer able to access the name property because it exists within this private data 82 00:05:21,260 --> 00:05:21,980 table. 83 00:05:22,340 --> 00:05:26,390 But let's say I want to be able to change the name from a function. 84 00:05:26,720 --> 00:05:32,300 Well, what I could do is I could create a function in the human meta table. 85 00:05:32,690 --> 00:05:35,120 We're going to call it change name. 86 00:05:36,490 --> 00:05:43,090 And what this function is going to do is it's going to get that private table we created here that is 87 00:05:43,090 --> 00:05:44,950 stored in the private data table. 88 00:05:45,160 --> 00:05:49,330 We're going to get it from the private data table and past self. 89 00:05:49,330 --> 00:05:52,510 Because remember self is the key for this table. 90 00:05:52,510 --> 00:05:59,650 And from that point we can set private dot name equal to the new name that is passed to this function. 91 00:06:00,630 --> 00:06:01,830 Equal to name. 92 00:06:02,040 --> 00:06:07,050 And then I'm also going to create a function called speak. 93 00:06:07,050 --> 00:06:09,510 So human meta table speak. 94 00:06:10,140 --> 00:06:13,200 And what this can do is print out. 95 00:06:13,200 --> 00:06:15,450 We get the private data table. 96 00:06:15,450 --> 00:06:19,320 We pass self to it as the key and we can get the name. 97 00:06:19,320 --> 00:06:22,590 And we'll print something like Bob says hi. 98 00:06:25,600 --> 00:06:32,500 And now when I call this function on my new human speak, it should print. 99 00:06:32,500 --> 00:06:33,250 Bob says hi. 100 00:06:33,280 --> 00:06:34,360 So let's run that. 101 00:06:35,350 --> 00:06:35,650 We get? 102 00:06:35,650 --> 00:06:36,370 Bob says hi. 103 00:06:36,400 --> 00:06:37,330 Perfect. 104 00:06:38,200 --> 00:06:43,750 And now that means I should also remove the name property from my human meta table. 105 00:06:44,380 --> 00:06:50,350 So I've removed it from the meta table, and now the name only exists within this private table that 106 00:06:50,350 --> 00:06:52,990 gets stored within this private data table. 107 00:06:53,020 --> 00:06:57,160 That means in my new human, I can no longer access the name. 108 00:06:57,190 --> 00:06:59,650 It's not possible for me to access it anymore. 109 00:06:59,650 --> 00:07:06,100 But since I've created this change name table, I can call it on my new human change name. 110 00:07:06,310 --> 00:07:08,380 And I could change it to something like Jerry. 111 00:07:08,410 --> 00:07:10,180 So instead it should print. 112 00:07:10,180 --> 00:07:12,730 Jerry says hi instead of Bob says hi. 113 00:07:12,760 --> 00:07:14,050 So if we hit run. 114 00:07:14,800 --> 00:07:15,370 There we go. 115 00:07:15,370 --> 00:07:16,360 Jerry says hi. 116 00:07:17,170 --> 00:07:23,440 So this is the main idea of encapsulation, limiting access to data and grouping functions together 117 00:07:23,440 --> 00:07:24,790 into a single unit. 118 00:07:24,790 --> 00:07:31,840 Because I don't want the constructor, the new function, to be part of any object that I create from 119 00:07:31,840 --> 00:07:39,430 the class, I put it alone into its own table, and then every other function that I need to use on 120 00:07:39,430 --> 00:07:42,310 the objects themselves like to speak or change the name. 121 00:07:42,310 --> 00:07:46,060 It is stored in a separate table that is actually used as the meta table. 122 00:07:46,060 --> 00:07:49,930 So let's go through this script one more time to make sure you understand everything. 123 00:07:50,320 --> 00:07:56,680 So our human table, which is acting as our class, only has the constructor inside of it. 124 00:07:56,680 --> 00:08:03,190 And inside this constructor we create a new table and we set it to this human meta table. 125 00:08:03,190 --> 00:08:09,040 And this human meta table is the one that has the index meta methods and has these other functions for 126 00:08:09,040 --> 00:08:12,340 changing the name and having the human speak. 127 00:08:13,460 --> 00:08:20,390 After that, we create a new table called private, and instead of setting the name of our human directly 128 00:08:20,390 --> 00:08:25,100 on this table, the self that gets returned, we store it in this private table. 129 00:08:25,880 --> 00:08:31,940 And then we store this private table and another table called private data, whose key is the table 130 00:08:31,940 --> 00:08:33,680 itself, the object itself. 131 00:08:33,680 --> 00:08:36,950 And that's how we can get access to the data like the name. 132 00:08:37,840 --> 00:08:43,570 That means when we go to change the name of our object, it has to get the table itself. 133 00:08:43,570 --> 00:08:49,840 It references it from the private data table, getting its key because self is passed to this function. 134 00:08:49,840 --> 00:08:54,130 And then from that point we can change the name to this new name passed to the function. 135 00:08:54,700 --> 00:08:59,500 So that means when we create a new human right here and give it the name Bob, it's going to store the 136 00:08:59,500 --> 00:09:03,940 name Bob inside of this private table which is stored in this private data table. 137 00:09:04,420 --> 00:09:10,420 And any time we go to change the name, we have to call this function because the name is not stored 138 00:09:10,420 --> 00:09:13,750 directly within the object, but instead inside this table. 139 00:09:14,360 --> 00:09:18,140 So it goes, gets the table and then changes the name. 140 00:09:18,290 --> 00:09:21,200 And then from that point we can use the speak function. 141 00:09:21,850 --> 00:09:25,750 And then we can get the name again from accessing the private data table. 142 00:09:25,840 --> 00:09:28,090 And then we can say something like says hi. 143 00:09:29,380 --> 00:09:33,730 So when you take all this functionality, you want to store it inside of a module script. 144 00:09:34,470 --> 00:09:39,750 And because you're storing it inside of a module script, no other script will be able to have access 145 00:09:39,750 --> 00:09:42,450 to this data here because it is local. 146 00:09:42,450 --> 00:09:46,350 It's hidden away from all the other scripts that require the module script. 147 00:09:46,980 --> 00:09:52,620 So this lecture may have been a little bit confusing, but again, the main idea of encapsulation is 148 00:09:52,620 --> 00:09:56,790 to limit access to data and group functions together into a single unit. 149 00:09:56,820 --> 00:09:58,290 See you in the next lecture.